# load libraries
# load libraries
library(clusterSim) 
library(FlowSOM)
library(flowCore)
library(cluster)
library(fpc)
library(clv)
library(Seurat)
library(dplyr)
library(ggplot2)
library(clustree)
library(reshape2)

Visialize correlations on UMAP

# read in correlation

# read in Seurat object to make UMAP
seu <- readRDS("/Users/rhalenathomas/Documents/Data/FlowCytometry/PhenoID/Analysis/9MBO/prepro_outsjan20-9000cells/Figure3/cluster_parameters/LouvainFinal/FlowAlignRetroTransLouvainSeuratObject60.Rds")


# keep feature order the same as in other figures

AB <- c("CD24","CD56","CD29","CD15","CD184","CD133","CD71","CD44","GLAST","AQP4","HepaCAM", "CD140a","O4")

Add the cell labels into seurat object

unique(seu$cor.labels)
 [1] "OPC"                    "RG"                     "Astrocyte"              "Endothelial"            "Neuron-OPC"            
 [6] "OPC-Epithelial"         "Astrocyte-RG"           "StemCell"               "Epithelial"             "OPC-Neuron"            
[11] "Oligo"                  "RG-Endothelial"         "RG-Astrocyte"           "StemCell-OPC"           "Neuron"                
[16] "Epithelial-Endothelial" "StemCell-Neuron"        "Endothelial-RG"         "OPC-StemCell"           "Astrocyte-Endothelial" 
[21] "StemCell-Oligo"         "NPC"                    "Endothelial-Astrocyte"  "Epithelial-OPC"         "Endothelial-Epithelial"
[26] "Neuron-NPC"             "Epithelial-StemCell"    "RG-OPC"                 "Astrocyte-NPC"          "StemCell-Endothelial"  
[31] "OPC-Oligo"              "RG-Oligo"               "Oligo-StemCell"         "NPC-StemCell"           "Neuron-RG"             
[36] "OPC-RG"                 "NPC-Astrocyte"          "RG-NPC"                 "Epithelial-RG"          "RG-Neuron"             
[41] "RG-Epithelial"          "NPC-Neuron"             "Oligo-RG"               "Astrocyte-OPC"          "OPC-Astrocyte"         
[46] "OPC-Endothelial"        "Neuron-Endothelial"     "Neuron-Astrocyte"       "Neuron-StemCell"        "StemCell-Epithelial"   
[51] "Epithelial-NPC"         "StemCell-NPC"           "Endothelial-StemCell"   "Epithelial-Astrocyte"   "Oligo-OPC"             
[56] "Oligo-Neuron"           "Oligo-NPC"              "Epithelial-Oligo"       "OPC-NPC"                "StemCell-RG"           
[61] "unknown"                "NPC-RG"                 "Oligo-Epithelial"       "Endothelial-Neuron"     "Astrocyte-Epithelial"  
[66] "NPC-OPC"                "Astrocyte-Oligo"        "Neuron-Oligo"           "Endothelial-Oligo"      "NPC-Endothelial"       
[71] "NPC-Oligo"              "Oligo-Astrocyte"        "Endothelial-NPC"        "StemCell-Astrocyte"     "Endothelial-OPC"       
[76] "Astrocyte-StemCell"     "Oligo-Endothelial"      "Astrocyte-Neuron"       "RG-StemCell"            "NPC-Epithelial"        
[81] "Epithelial-Neuron"      "Neuron-Epithelial"     

Make UMAP

Save UMAPS

pdf(paste(outpath,"UMAPCorLables9celltypes202203018.pdf"), width = 20, height = 8)
DimPlot(seu, reduction = "umap", label = TRUE, group.by = 'cor.labels', repel = TRUE, shuffle = TRUE)
Warning: ggrepel: 25 unlabeled data points (too many overlaps). Consider increasing max.overlaps
dev.off()
null device 
          1 

Add labels

0-Epithelial 1-Astrocytes-RG 2-Neurons 3-NPC (neural stem) 4-RG-CD133 5-RG-CD184 6-Astrocytes 7-Neurons-early 8-Astrocytes 9-Glia (RG/neuron) 10-Endothelial 11-Oligodendrocytes 12-mix 13-OPC 14-Neurons-early


pdf(paste(outpath,"HeatMapcell20220318.pdf"), width = 8, height = 5)
DoHeatmap(seu, group.by = 'labels4', features = AB, size= 5,slot = "scale.data", disp.max = 2, disp.min = -1.5) + scale_fill_gradientn(colors = c("#154c79", "#eeeee4", "#e28743")) + 
  theme(axis.text.y = element_text(size = 15))
Scale for 'fill' is already present. Adding another scale for 'fill', which will replace the existing scale.
dev.off()
null device 
          1 

Visualize split UMAPs by batch

pdf(paste(outpath,"UMAPsplitBatch_clusterlabels2.pdf"), width = 30, height = 5)
  DimPlot(seu, split.by = 'Batch', label = TRUE)
dev.off()
null device 
          1 

Plot the correlations with less mix-cell types

Try to calculate how many of each cell type are in each cluster


# total proportion in each cell type
table(seu$RNA_snn_res.0.4)

    0     1     2     3     4     5     6     7     8     9    10    11    12    13    14 
20874 10783  8565  6789  6024  5703  3296  3033  2632  2535  2379   430   245   185   105 
table(seu$labels4)

   Epithelial  Astrocytes-1       Neurons           NPC          RG-1          RG-2  Astrocytes-2 
        20874         13415          8565          6789          6024          5703          5831 
Neurons-early   Endothelial         Oligo           mix           OPC 
         3138          2379           430           245           185 
#proportions
prop.table(table(seu$labels4))

   Epithelial  Astrocytes-1       Neurons           NPC          RG-1          RG-2  Astrocytes-2 
  0.283698932   0.182323521   0.116407078   0.092269428   0.081872299   0.077509582   0.079249232 
Neurons-early   Endothelial         Oligo           mix           OPC 
  0.042648618   0.032333034   0.005844138   0.003329800   0.002514339 

Proportions of each sample:

Use correlation labels to help label clusters


cor.lables <- as.data.frame(table(seu$RNA_snn_res.1.2, seu$cor.labels))
cor.lables$Freq <- as.double(cor.lables$Freq)
# try to make a heatmap

# not working
hm <- ggplot(data = pr.cor.lables, mapping = aes(x= Var1, y = Var2, fill = Freq))
hm


# try bar chart
ggplot(cor.lables, aes(y = Freq, x = Var1, fill = Var2)) + geom_bar(position = "stack", stat= "identity")

See the same format of UMAP

DimPlot(seu, group.by = "RNA_snn_res.1.2", label = TRUE)

Make a lot of rigde plots

RidgePlot(seu, group.by = "RNA_snn_res.1.2", features = "CD140a", log = TRUE)
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.131
Warning: Removed 44076 rows containing non-finite values (stat_density_ridges).

Add some new labels from resolution 1.2

See the expression in each group in ridge plot


RidgePlot(seu, group.by = "labels4", features = AB, log = TRUE)
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.105
Warning: Removed 21734 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.0805
Warning: Removed 618 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.0772
Warning: Removed 13691 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.0901
Warning: Removed 14795 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.0884
Warning: Removed 11826 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.0756
Warning: Removed 15435 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.0806
Warning: Removed 17617 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.114
Warning: Removed 1308 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.13
Warning: Removed 27822 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.102
Warning: Removed 21525 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.094
Warning: Removed 28052 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.102
Warning: Removed 44076 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.0867
Warning: Removed 11933 rows containing non-finite values (stat_density_ridges).

RidgePlot(seu, group.by = "labels6", features = AB, log = TRUE)
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Scale for 'x' is already present. Adding another scale for 'x', which will replace the existing scale.
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.102
Warning: Removed 21734 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.0764
Warning: Removed 618 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.0799
Warning: Removed 13691 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.0917
Warning: Removed 14795 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.0787
Warning: Removed 11826 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.0809
Warning: Removed 15435 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.0869
Warning: Removed 17617 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.105
Warning: Removed 1308 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.119
Warning: Removed 27822 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.102
Warning: Removed 21525 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.0885
Warning: Removed 28052 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.101
Warning: Removed 44076 rows containing non-finite values (stat_density_ridges).
Warning in self$trans$transform(x) : NaNs produced
Warning: Transformation introduced infinite values in continuous x-axis
Picking joint bandwidth of 0.0747
Warning: Removed 11933 rows containing non-finite values (stat_density_ridges).

Get mean expression per group/cell type of each antibody

Label transfer using Seurat

anchors <- FindTransferAnchors(reference = seu, query = seu.q, features = AB, reference.reduction = "pca", dim= 1:10) 
Projecting cell embeddings
Finding neighborhoods

Maybe the dotplot can work now??? Nope - but it worked once before so why not now????

seu <- ScaleData(seu)
Centering and scaling data matrix

  |                                                                                                           
  |                                                                                                     |   0%
  |                                                                                                           
  |=====================================================================================================| 100%
DotPlot(seu, features = AB, cols = c("red","blue"), group.by = 'RNA_snn_res.0.4', dot.scale = 8) + RotatedAxis()

LS0tCnRpdGxlOiAiUiBOb3RlYm9vayIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKCmBgYHtyfQojIGxvYWQgbGlicmFyaWVzCiMgbG9hZCBsaWJyYXJpZXMKbGlicmFyeShjbHVzdGVyU2ltKSAKbGlicmFyeShGbG93U09NKQpsaWJyYXJ5KGZsb3dDb3JlKQpsaWJyYXJ5KGNsdXN0ZXIpCmxpYnJhcnkoZnBjKQpsaWJyYXJ5KGNsdikKbGlicmFyeShTZXVyYXQpCmxpYnJhcnkoZHBseXIpCmxpYnJhcnkoZ2dwbG90MikKbGlicmFyeShjbHVzdHJlZSkKbGlicmFyeShyZXNoYXBlMikKCmBgYAoKVmlzaWFsaXplIGNvcnJlbGF0aW9ucyBvbiBVTUFQCgpgYGB7cn0KIyByZWFkIGluIGNvcnJlbGF0aW9uCgojIHJlYWQgaW4gU2V1cmF0IG9iamVjdCB0byBtYWtlIFVNQVAKc2V1IDwtIHJlYWRSRFMoIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0RvY3VtZW50cy9EYXRhL0Zsb3dDeXRvbWV0cnkvUGhlbm9JRC9BbmFseXNpcy85TUJPL3ByZXByb19vdXRzamFuMjAtOTAwMGNlbGxzL0ZpZ3VyZTMvY2x1c3Rlcl9wYXJhbWV0ZXJzL0xvdXZhaW5GaW5hbC9GbG93QWxpZ25SZXRyb1RyYW5zTG91dmFpblNldXJhdE9iamVjdDYwLlJkcyIpCgoKIyBrZWVwIGZlYXR1cmUgb3JkZXIgdGhlIHNhbWUgYXMgaW4gb3RoZXIgZmlndXJlcwoKQUIgPC0gYygiQ0QyNCIsIkNENTYiLCJDRDI5IiwiQ0QxNSIsIkNEMTg0IiwiQ0QxMzMiLCJDRDcxIiwiQ0Q0NCIsIkdMQVNUIiwiQVFQNCIsIkhlcGFDQU0iLCAiQ0QxNDBhIiwiTzQiKQoKCgpgYGAKCgpBZGQgdGhlIGNlbGwgbGFiZWxzIGludG8gc2V1cmF0IG9iamVjdAoKYGBge3J9Cgpjb3IgPC0gcmVhZC5jc3YoIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0RvY3VtZW50cy9EYXRhL0Zsb3dDeXRvbWV0cnkvUGhlbm9JRC9BbmFseXNpcy85TUJPL3ByZXByb19vdXRzamFuMjAtOTAwMGNlbGxzL0ZpZ3VyZTMvY29ycmVsYXRpb24vcmV0cm8vOWNlbGx0eXBlcy9jb3JyX2NlbGx0eXBlcy5jc3YiKQoKc2V1IDwtIEFkZE1ldGFEYXRhKG9iamVjdD1zZXUsIG1ldGFkYXRhPWNvciRjZWxsLmxhYmVsLCBjb2wubmFtZSA9ICdjb3IubGFiZWxzJykKdW5pcXVlKHNldSRjb3IubGFiZWxzKQoKYGBgCgoKTWFrZSBVTUFQCgoKYGBge3J9CnNldSA8LSBSdW5VTUFQKHNldSxzcHJlYWQgPSAxLjIsIG1pbi5kaXN0ID0gMC4yNSwgZGltcyA9IDE6MTIpCkRpbVBsb3Qoc2V1LCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVFJVRSwgZ3JvdXAuYnkgPSAnUk5BX3Nubl9yZXMuMC40JywgcmVwZWwgPSBUUlVFKQoKRGltUGxvdChzZXUsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgbGFiZWwgPSBGQUxTRSwgZ3JvdXAuYnkgPSAnY29yLmxhYmVscycsIHJlcGVsID0gVFJVRSkgIysgdGhlbWUobGVnZW5kLnBvc2l0aW9uID0ibm9uZSIpCgoKCgpgYGAKCgpTYXZlIFVNQVBTCgpgYGB7cn0KCm91dHBhdGggPC0gIi9Vc2Vycy9yaGFsZW5hdGhvbWFzL0RvY3VtZW50cy9EYXRhL0Zsb3dDeXRvbWV0cnkvUGhlbm9JRC9BbmFseXNpcy85TUJPL3ByZXByb19vdXRzamFuMjAtOTAwMGNlbGxzL0ZpZ3VyZTMvIgoKcGRmKHBhc3RlKG91dHBhdGgsIlVNQVBDb3JMYWJsZXM5Y2VsbHR5cGVzMjAyMjAzMDE4LnBkZiIpLCB3aWR0aCA9IDIwLCBoZWlnaHQgPSA4KQpEaW1QbG90KHNldSwgcmVkdWN0aW9uID0gInVtYXAiLCBsYWJlbCA9IFRSVUUsIGdyb3VwLmJ5ID0gJ2Nvci5sYWJlbHMnLCByZXBlbCA9IFRSVUUsIHNodWZmbGUgPSBUUlVFKQpkZXYub2ZmKCkKCgpwZGYocGFzdGUob3V0cGF0aCwiRmlnM1VNQVAyMDIyMDMwMTgucGRmIiksIHdpZHRoID0gMTIsIGhlaWdodCA9IDYpCkRpbVBsb3Qoc2V1LCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVFJVRSwgZ3JvdXAuYnkgPSAnUk5BX3Nubl9yZXMuMC40JywgcmVwZWwgPSBUUlVFKQpkZXYub2ZmKCkKCgoKIyBzYXZlIHRoZSBjbHVzdGVycwoKI3BkZihwYXN0ZShvdXRwYXRoLCJVTUFQbG91dms2MHJlczAyQ2x1c3RlcnMucGRmIiksIHdpZHRoID0gMjAsIGhlaWdodCA9IDgpCiNEaW1QbG90KHNldSwgcmVkdWN0aW9uID0gInVtYXAiLCBsYWJlbCA9IFRSVUUsIGdyb3VwLmJ5ID0gJ1JOQV9zbm5fcmVzLjAuNScsIHJlcGVsID0gVFJVRSkKI2Rldi5vZmYoKQoKCmBgYAoKCmBgYHtyfQojIHNhdmUgZmVhdHVyZSBwbG90IHdpdGggbmV3IFVNQVAgc3RydWN0dXJlIGFuZCBiZXR0ZXIgZGltZW5zaW9ucwpwZGYocGFzdGUob3V0cGF0aCwiVU1BUGxvdXZrNjByZXMwMkZlYXR1cmVQbG90cy5wZGYiKSwgd2lkdGggPSAyMCwgaGVpZ2h0ID0gOCkKRmVhdHVyZVBsb3Qoc2V1LCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gQUIsc2xvdCA9ICdzY2FsZS5kYXRhJyxtaW4uY3V0b2ZmID0gJ3ExJywgbWF4LmN1dG9mZiA9Jzk5JyxsYWJlbC5zaXplID0gMSkrIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDAuMSkpCmRldi5vZmYoKQoKRmVhdHVyZVBsb3Qoc2V1LCByZWR1Y3Rpb24gPSAidW1hcCIsIGZlYXR1cmVzID0gQUIsc2xvdCA9ICdzY2FsZS5kYXRhJyxsYWJlbC5zaXplID0gMSkrIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDAuMSkpCgoKCgpgYGAKCgpBZGQgbGFiZWxzCgowLUVwaXRoZWxpYWwKMS1Bc3Ryb2N5dGVzLVJHCjItTmV1cm9ucwozLU5QQyAobmV1cmFsIHN0ZW0pCjQtUkctQ0QxMzMKNS1SRy1DRDE4NAo2LUFzdHJvY3l0ZXMKNy1OZXVyb25zLWVhcmx5CjgtQXN0cm9jeXRlcwo5LUdsaWEgKFJHL25ldXJvbikKMTAtRW5kb3RoZWxpYWwKMTEtT2xpZ29kZW5kcm9jeXRlcwoxMi1taXgKMTMtT1BDCjE0LU5ldXJvbnMtZWFybHkKCgpgYGB7cn0KSWRlbnRzKHNldSkgPC0gIlJOQV9zbm5fcmVzLjAuNCIKY2x1c3Rlci5pZHMgPC0gYygiRXBpdGhlbGlhbCIsIkFzdHJvLVJHIiwiTmV1cm9ucyIsIk5QQyIsIlJHLTEiLCJSRy0yIiwiQXN0cm8tMSIsIk5ldXJvbnMtZWFybHkiLCJBc3Ryby0yIiwiR2xpYSIsIkVuZG90aGVsaWFsIiwiT2xpZ28iLCJtaXgiLCJPUEMiLCJOZXVyb25zLWVhcmx5IikKCm5hbWVzKGNsdXN0ZXIuaWRzKSA8LSBsZXZlbHMoc2V1KQpzZXUgPC0gUmVuYW1lSWRlbnRzKHNldSwgY2x1c3Rlci5pZHMpCnNldSRsYWJlbHMgPC0gSWRlbnRzKHNldSkKCkRpbVBsb3Qoc2V1LCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVFJVRSwgZ3JvdXAuYnkgPSAnbGFiZWxzJywgcmVwZWwgPSBUUlVFKQoKIyBmZXcgbGFiZWxzCgpJZGVudHMoc2V1KSA8LSAiUk5BX3Nubl9yZXMuMC40IgpjbHVzdGVyLmlkcyA8LSBjKCJFcGl0aGVsaWFsIiwiQXN0cm9jeXRlcyIsIk5ldXJvbnMiLCJOZXVyYWwtU3RlbSIsIlJHIiwiUkciLCJBc3Ryb2N5dGVzIiwiTmV1cm9ucy1lYXJseSIsIkFzdHJvY3l0ZXMiLCJSRyIsIkVuZG90aGVsaWFsIiwiT2xpZ28iLCJtaXgiLCJPUEMiLCJOZXVyb25zLWVhcmx5IikKCm5hbWVzKGNsdXN0ZXIuaWRzKSA8LSBsZXZlbHMoc2V1KQpzZXUgPC0gUmVuYW1lSWRlbnRzKHNldSwgY2x1c3Rlci5pZHMpCnNldSRsYWJlbHMyIDwtIElkZW50cyhzZXUpCgpEaW1QbG90KHNldSwgcmVkdWN0aW9uID0gInVtYXAiLCBsYWJlbCA9IFRSVUUsIGdyb3VwLmJ5ID0gJ2xhYmVsczInLCByZXBlbCA9IFRSVUUpCgoKSWRlbnRzKHNldSkgPC0gIlJOQV9zbm5fcmVzLjAuNCIKY2x1c3Rlci5pZHMgPC0gYygiRXBpdGhlbGlhbCIsIkFzdHJvIiwiTmV1cm9ucyIsIk5QQyIsIlJHLTEiLCJSRy0yIiwiQXN0cm8iLCJOZXVyb25zLWVhcmx5IiwiQXN0cm8iLCJHbGlhIiwiRW5kb3RoZWxpYWwiLCJPbGlnbyIsIm1peCIsIk9QQyIsIk5ldXJvbnMtZWFybHkiKQoKbmFtZXMoY2x1c3Rlci5pZHMpIDwtIGxldmVscyhzZXUpCnNldSA8LSBSZW5hbWVJZGVudHMoc2V1LCBjbHVzdGVyLmlkcykKc2V1JGxhYmVsczMgPC0gSWRlbnRzKHNldSkKCkRpbVBsb3Qoc2V1LCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVFJVRSwgZ3JvdXAuYnkgPSAnbGFiZWxzMycsIHJlcGVsID0gVFJVRSkKCklkZW50cyhzZXUpIDwtICJSTkFfc25uX3Jlcy4wLjQiCmNsdXN0ZXIuaWRzIDwtIGMoIkVwaXRoZWxpYWwiLCJBc3Ryb2N5dGVzLTEiLCJOZXVyb25zIiwiTlBDIiwiUkctMSIsIlJHLTIiLCJBc3Ryb2N5dGVzLTIiLCJOZXVyb25zLWVhcmx5IiwiQXN0cm9jeXRlcy0xIiwiQXN0cm9jeXRlcy0yIiwiRW5kb3RoZWxpYWwiLCJPbGlnbyIsIm1peCIsIk9QQyIsIk5ldXJvbnMtZWFybHkiKQoKbmFtZXMoY2x1c3Rlci5pZHMpIDwtIGxldmVscyhzZXUpCnNldSA8LSBSZW5hbWVJZGVudHMoc2V1LCBjbHVzdGVyLmlkcykKc2V1JGxhYmVsczQgPC0gSWRlbnRzKHNldSkKCkRpbVBsb3Qoc2V1LCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVFJVRSwgZ3JvdXAuYnkgPSAnbGFiZWxzNCcsIHJlcGVsID0gVFJVRSkKCgpgYGAKCgpgYGB7cn0KIyBzYXZlIHRoZSBsYWJlbGxlZCBzZXVyYXQgb2JqZWN0IHRvIGFwcGx5IGxhYmVscyB0byBvdGhlciBjbHVzdGVyaW5nCiMgdXNlIGFuIGlucHV0cyB0byBSYW5kb20gRm9yZXN0CnNhdmVSRFMoc2V1LCIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb2N1bWVudHMvRGF0YS9GbG93Q3l0b21ldHJ5L1BoZW5vSUQvQW5hbHlzaXMvOU1CTy9wcmVwcm9fb3V0c2phbjIwLTkwMDBjZWxscy9GaWd1cmUzL0xvdXZrbjYwRGlmZmVyZW50Q2VsbExhYmVsczIyMDIyMDMxOC5SZHMiKQoKCiMgc2F2ZSBzb21lIHBsb3RzCnBkZihwYXN0ZShvdXRwYXRoLCJVTUFQY2VsbHR5cGUyMDIyMDMxOC5wZGYiKSwgd2lkdGggPSA4LCBoZWlnaHQgPSA1KQpEaW1QbG90KHNldSwgcmVkdWN0aW9uID0gInVtYXAiLCBsYWJlbCA9IFRSVUUsIGdyb3VwLmJ5ID0gJ2xhYmVsczQnLCByZXBlbCA9IFRSVUUsIHNodWZmbGUgPSBUUlVFLCBsYWJlbC5zaXplID0gNSkKZGV2Lm9mZigpCgoKCnBkZihwYXN0ZShvdXRwYXRoLCJIZWF0TWFwY2VsbDIwMjIwMzE4LnBkZiIpLCB3aWR0aCA9IDgsIGhlaWdodCA9IDUpCkRvSGVhdG1hcChzZXUsIGdyb3VwLmJ5ID0gJ2xhYmVsczQnLCBmZWF0dXJlcyA9IEFCLCBzaXplPSA1LHNsb3QgPSAic2NhbGUuZGF0YSIsIGRpc3AubWF4ID0gMiwgZGlzcC5taW4gPSAtMS41KSArIHNjYWxlX2ZpbGxfZ3JhZGllbnRuKGNvbG9ycyA9IGMoIiMxNTRjNzkiLCAiI2VlZWVlNCIsICIjZTI4NzQzIikpICsgCiAgdGhlbWUoYXhpcy50ZXh0LnkgPSBlbGVtZW50X3RleHQoc2l6ZSA9IDE1KSkKZGV2Lm9mZigpCgoKYGBgCgpWaXN1YWxpemUgc3BsaXQgVU1BUHMgYnkgYmF0Y2ggCgpgYGB7cn0Kb3V0cGF0aCA8LSAiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG9jdW1lbnRzL0RhdGEvRmxvd0N5dG9tZXRyeS9QaGVub0lEL0FuYWx5c2lzLzlNQk8vcHJlcHJvX291dHNqYW4yMC05MDAwY2VsbHMvRmlndXJlMy8iCgpwZGYocGFzdGUob3V0cGF0aCwiVU1BUHNwbGl0QmF0Y2hfY2x1c3RlcmxhYmVsczIucGRmIiksIHdpZHRoID0gMzAsIGhlaWdodCA9IDUpCiAgRGltUGxvdChzZXUsIHNwbGl0LmJ5ID0gJ0JhdGNoJywgbGFiZWwgPSBUUlVFKQpkZXYub2ZmKCkKCgpGZWF0dXJlUGxvdChzZXUsIHNwbGl0LmJ5ID0gJ0JhdGNoJywgZmVhdHVyZXMgPSAiQ0QyNCIpCkRpbVBsb3Qoc2V1LCBncm91cC5ieSA9ICdCYXRjaCcsIGxhYmVsID0gRkFMU0UsIHNodWZmbGUgPSBUUlVFKQoKCmBgYAoKUGxvdCB0aGUgY29ycmVsYXRpb25zIHdpdGggbGVzcyBtaXgtY2VsbCB0eXBlcwoKYGBge3J9CiBkZi5maWx0ZXIgPC0gY29yICU+JSBncm91cF9ieShjZWxsLmxhYmVsKSAlPiUgZHBseXI6OmZpbHRlcihuKCk+IDUwMCkKCnBsb3QxIDwtIGdncGxvdChkZi5maWx0ZXIsIGFlcyh4PXJlb3JkZXIoY2VsbC5sYWJlbCxjZWxsLmxhYmVsLGZ1bmN0aW9uKHgpLWxlbmd0aCh4KSksIGZpbGwgPSBjZWxsLmxhYmVsKSkrIGdlb21fYmFyKCkrdGhlbWVfY2xhc3NpYygpICsKICAgdGhlbWUoYXhpcy50ZXh0Lng9ZWxlbWVudF90ZXh0KGFuZ2xlPTkwKSkrIHhsYWIoJ0Fzc2lnbmVkIGNlbGwgdHlwZScpICsgeWxhYignbnVtYmVyIG9mIGNlbGwnKQogIHByaW50KHBsb3QxKQoKICAjICMgcGxvdAogIHBkZihwYXN0ZShvdXRwYXRoLCJGcmVxQ2VsbFR5cGVzX2ZpbHQ1MDAucGRmIixzZXA9IiIpLHdpZHRoID0xMiwgaGVpZ2h0ID0gNikKICBwbG90MSA8LSBnZ3Bsb3QoZGYuZmlsdGVyLCBhZXMoeD1yZW9yZGVyKGNlbGwubGFiZWwsY2VsbC5sYWJlbCxmdW5jdGlvbih4KS1sZW5ndGgoeCkpLCBmaWxsID0gY2VsbC5sYWJlbCkpKyBnZW9tX2JhcigpK3RoZW1lX2NsYXNzaWMoKSArCiAgIHRoZW1lKGF4aXMudGV4dC54PWVsZW1lbnRfdGV4dChhbmdsZT05MCkpKyB4bGFiKCdBc3NpZ25lZCBjZWxsIHR5cGUnKSArIHlsYWIoJ251bWJlciBvZiBjZWxsJykKICBwcmludChwbG90MSkKICBkZXYub2ZmKCkKCgpgYGAKCgpUcnkgdG8gY2FsY3VsYXRlIGhvdyBtYW55IG9mIGVhY2ggY2VsbCB0eXBlIGFyZSBpbiBlYWNoIGNsdXN0ZXIKCmBgYHtyfQoKIyB0b3RhbCBwcm9wb3J0aW9uIGluIGVhY2ggY2VsbCB0eXBlCnRhYmxlKHNldSRSTkFfc25uX3Jlcy4wLjQpCgoKYGBgCgoKYGBge3J9CnRhYmxlKHNldSRsYWJlbHM0KQojcHJvcG9ydGlvbnMKcHJvcC50YWJsZSh0YWJsZShzZXUkbGFiZWxzNCkpCgpgYGAKCgpgYGB7cn0KCiMgY29yIGxhYmVscyBwZXIgY2x1c3RlciBsYWJlbD8/Cgpjb3IubGFibGVzIDwtIGFzLmRhdGEuZnJhbWUodGFibGUoc2V1JGxhYmVsczQsIHNldSRjb3IubGFiZWxzKSkKcHIuY29yLmxhYmxlcyA8LSBhcy5kYXRhLmZyYW1lKHByb3AudGFibGUodGFibGUoc2V1JGxhYmVsczQsIHNldSRjb3IubGFiZWxzKSkpCmNvci5sYWJsZXMkRnJlcSA8LSBhcy5kb3VibGUoY29yLmxhYmxlcyRGcmVxKQojIHRyeSB0byBtYWtlIGEgaGVhdG1hcAoKIyBub3Qgd29ya2luZwpobSA8LSBnZ3Bsb3QoZGF0YSA9IHByLmNvci5sYWJsZXMsIG1hcHBpbmcgPSBhZXMoeD0gVmFyMSwgeSA9IFZhcjIsIGZpbGwgPSBGcmVxKSkKaG0KCiMgdHJ5IGJhciBjaGFydApnZ3Bsb3QoY29yLmxhYmxlcywgYWVzKHkgPSBGcmVxLCB4ID0gVmFyMSwgZmlsbCA9IFZhcjIpKSArIGdlb21fYmFyKHBvc2l0aW9uID0gInN0YWNrIiwgc3RhdD0gImlkZW50aXR5IikKCgojRmlsdGVyIGJ5IG1vc3QgZnJlcXVlbnQgcGVyIGdyb3VwCgoKCgpgYGAKCgpQcm9wb3J0aW9ucyBvZiBlYWNoIHNhbXBsZToKCmBgYHtyfQpzYW1wbGUubGFibGVzIDwtIGFzLmRhdGEuZnJhbWUodGFibGUoc2V1JEJhdGNoLCBzZXUkbGFiZWxzNCkpCgpzYW1wbGUubGFibGVzJEZyZXEgPC0gYXMuZG91YmxlKHNhbXBsZS5sYWJsZXMkRnJlcSkKIyB0cnkgdG8gbWFrZSBhIGhlYXRtYXAKCgojIHRyeSBiYXIgY2hhcnQKZ2dwbG90KHNhbXBsZS5sYWJsZXMsIGFlcyh5ID0gRnJlcSwgeCA9IFZhcjEsIGZpbGwgPSBWYXIyKSkgKyBnZW9tX2Jhcihwb3NpdGlvbiA9ICJzdGFjayIsIHN0YXQ9ICJpZGVudGl0eSIpKyB0aGVtZV9jbGFzc2ljKCkgKyB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoYW5nbGU9OTApKSsgeGxhYignQmF0Y2gnKSArIHlsYWIoJ0ZyZXF1ZW5jeSBvZiBDZWxsIHR5cGUnKQoKCgpgYGAKCgpVc2UgY29ycmVsYXRpb24gbGFiZWxzIHRvIGhlbHAgbGFiZWwgY2x1c3RlcnMKCmBgYHtyfQoKY29yLmxhYmxlcyA8LSBhcy5kYXRhLmZyYW1lKHRhYmxlKHNldSRSTkFfc25uX3Jlcy4xLjIsIHNldSRjb3IubGFiZWxzKSkKY29yLmxhYmxlcyRGcmVxIDwtIGFzLmRvdWJsZShjb3IubGFibGVzJEZyZXEpCiMgdHJ5IHRvIG1ha2UgYSBoZWF0bWFwCgoKIyB0cnkgYmFyIGNoYXJ0CmdncGxvdChjb3IubGFibGVzLCBhZXMoeSA9IEZyZXEsIHggPSBWYXIxLCBmaWxsID0gVmFyMikpICsgZ2VvbV9iYXIocG9zaXRpb24gPSAic3RhY2siLCBzdGF0PSAiaWRlbnRpdHkiKQpgYGAKCgpTZWUgdGhlIHNhbWUgZm9ybWF0IG9mIFVNQVAKYGBge3J9CkRpbVBsb3Qoc2V1LCBncm91cC5ieSA9ICJSTkFfc25uX3Jlcy4xLjIiLCBsYWJlbCA9IFRSVUUpCgpgYGAKCgoKTWFrZSBhIGxvdCBvZiByaWdkZSBwbG90cwoKYGBge3J9CgoKUmlkZ2VQbG90KHNldSwgZ3JvdXAuYnkgPSAiUk5BX3Nubl9yZXMuMS4yIiwgZmVhdHVyZXMgPSBBQiwgbG9nID0gVFJVRSkKUmlkZ2VQbG90KHNldSwgZ3JvdXAuYnkgPSAiUk5BX3Nubl9yZXMuMS4yIiwgZmVhdHVyZXMgPSAiQ0QxNSIsIGxvZyA9IFRSVUUpClJpZGdlUGxvdChzZXUsIGdyb3VwLmJ5ID0gIlJOQV9zbm5fcmVzLjEuMiIsIGZlYXR1cmVzID0gIkNEMjkiLCBsb2cgPSBUUlVFKQpSaWRnZVBsb3Qoc2V1LCBncm91cC5ieSA9ICJSTkFfc25uX3Jlcy4xLjIiLCBmZWF0dXJlcyA9ICJDRDE4NCIsIGxvZyA9IFRSVUUpClJpZGdlUGxvdChzZXUsIGdyb3VwLmJ5ID0gIlJOQV9zbm5fcmVzLjEuMiIsIGZlYXR1cmVzID0gIkhlcGFDQU0iLCBsb2cgPSBUUlVFKQpSaWRnZVBsb3Qoc2V1LCBncm91cC5ieSA9ICJSTkFfc25uX3Jlcy4xLjIiLCBmZWF0dXJlcyA9ICJDRDI0IiwgbG9nID0gVFJVRSkKUmlkZ2VQbG90KHNldSwgZ3JvdXAuYnkgPSAiUk5BX3Nubl9yZXMuMS4yIiwgZmVhdHVyZXMgPSAiQ0Q1NiIsIGxvZyA9IFRSVUUpClJpZGdlUGxvdChzZXUsIGdyb3VwLmJ5ID0gIlJOQV9zbm5fcmVzLjEuMiIsIGZlYXR1cmVzID0gIkNENDQiLCBsb2cgPSBUUlVFKQpSaWRnZVBsb3Qoc2V1LCBncm91cC5ieSA9ICJSTkFfc25uX3Jlcy4xLjIiLCBmZWF0dXJlcyA9ICJBUVA0IiwgbG9nID0gVFJVRSkKUmlkZ2VQbG90KHNldSwgZ3JvdXAuYnkgPSAiUk5BX3Nubl9yZXMuMS4yIiwgZmVhdHVyZXMgPSAiQ0QxNDBhIiwgbG9nID0gVFJVRSkKCmBgYAoKQWRkIHNvbWUgbmV3IGxhYmVscyBmcm9tIHJlc29sdXRpb24gMS4yCgoKCmBgYHtyfQoKSWRlbnRzKHNldSkgPC0gIlJOQV9zbm5fcmVzLjEuMiIKY2x1c3Rlci5pZHMgPC0gYygiTWl4IiwiUkctMSIsIk5ldXJvbnMtTWl4IiwiTmV1cm9ucy0xIiwiTlBDIiwiQXN0cm8tMSIsIkdsaWEtMSIsIlJHLTIiLCJFYXJseU5ldXJvbi1lbmRvIiwiUkctMyIsIkVuZG90aGVsaWFsIiwiQXN0cm8tMiIsIk5ldXJvbnMiLCJHbGlhLTIiLCJBc3Ryby0zIiwiQXN0cm8tMiIsIlJHLTQiLCJHbGlhLTMiLCJOUEMiLCJBc3Ryby0xIiwiT2xpZ28iLCJtaXgiLCJPUEMiLCJFbmRvdGhlbGlhbCIsIkVhcmx5TmV1cm9uLTIiLCJFcGl0aGVsaWFsIikKCm5hbWVzKGNsdXN0ZXIuaWRzKSA8LSBsZXZlbHMoc2V1KQpzZXUgPC0gUmVuYW1lSWRlbnRzKHNldSwgY2x1c3Rlci5pZHMpCnNldSRsYWJlbHM1IDwtIElkZW50cyhzZXUpCgpEaW1QbG90KHNldSwgcmVkdWN0aW9uID0gInVtYXAiLCBsYWJlbCA9IFRSVUUsIGdyb3VwLmJ5ID0gJ2xhYmVsczUnLCByZXBlbCA9IFRSVUUpCgoKSWRlbnRzKHNldSkgPC0gIlJOQV9zbm5fcmVzLjEuMiIKY2x1c3Rlci5pZHMgPC0gYygiTWl4IiwiUkctMSIsIk5ldXJvbnMtTWl4IiwiTmV1cm9ucyIsIk5QQyIsIkFzdHJvLTEiLCJBc3Ryby0yIiwiUkctMiIsIkVhcmx5TmV1cm9ucyIsIlJHLTMiLCJFbmRvdGhlbGlhbCIsIkFzdHJvLTIiLCJOZXVyb25zIiwiQXN0cm8tMSIsIlJHLTEiLCJBc3Ryby0yIiwiUkctMiIsIkFzdHJvLTIiLCJOUEMiLCJBc3Ryby0xIiwiT2xpZ28iLCJNaXgiLCJPUEMiLCJFbmRvdGhlbGlhbCIsIkVhcmx5TmV1cm9ucyIsIkVwaXRoZWxpYWwiKQoKbmFtZXMoY2x1c3Rlci5pZHMpIDwtIGxldmVscyhzZXUpCnNldSA8LSBSZW5hbWVJZGVudHMoc2V1LCBjbHVzdGVyLmlkcykKc2V1JGxhYmVsczYgPC0gSWRlbnRzKHNldSkKCkRpbVBsb3Qoc2V1LCByZWR1Y3Rpb24gPSAidW1hcCIsIGxhYmVsID0gVFJVRSwgZ3JvdXAuYnkgPSAnbGFiZWxzNicsIHJlcGVsID0gVFJVRSkKCgoKYGBgCgoKCgoKClNlZSB0aGUgZXhwcmVzc2lvbiBpbiBlYWNoIGdyb3VwIGluIHJpZGdlIHBsb3QKCmBgYHtyfQoKUmlkZ2VQbG90KHNldSwgZ3JvdXAuYnkgPSAibGFiZWxzNCIsIGZlYXR1cmVzID0gQUIsIGxvZyA9IFRSVUUpCgpSaWRnZVBsb3Qoc2V1LCBncm91cC5ieSA9ICJsYWJlbHM2IiwgZmVhdHVyZXMgPSBBQiwgbG9nID0gVFJVRSkKCmBgYAoKCgoKCkdldCBtZWFuIGV4cHJlc3Npb24gcGVyIGdyb3VwL2NlbGwgdHlwZSAgb2YgZWFjaCBhbnRpYm9keSAKCmBgYHtyfQoKCmBgYAoKCgpMYWJlbCB0cmFuc2ZlciB1c2luZyBTZXVyYXQKCmBgYHtyfQojIHNpbmdsZSBjZWxsIHJlZmVyZW5jZSBtYXBwaW5nCiMgdXNlcyB0aGUgZnVuY3Rpb24gVHJhbnNmZXJEYXRhCgojIEknbGwgdHJ5IGEgZGlmZmVyZW50IGtuIGluIHRoZSBzYW1lIGRhdGEgYXMgdGhlIHF1ZXJ5CgpzZXUucSA8LSByZWFkUkRTKCIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb2N1bWVudHMvRGF0YS9GbG93Q3l0b21ldHJ5L1BoZW5vSUQvQW5hbHlzaXMvOU1CTy9wcmVwcm9fb3V0c2phbjIwLTkwMDBjZWxscy9GaWd1cmUzL2NsdXN0ZXJfcGFyYW1ldGVycy9Mb3V2YWluRmluYWwvRmxvd0FsaWduUmV0cm9UcmFuc0xvdXZhaW5TZXVyYXRPYmplY3QyMC5SZHMiKQoKIyB0aGUgY3VycmVudCBsYWJlbGxlZCBzZXVyYXQgb2JqZWN0IHdpbGwgYmUgdGhlIHJlZmVyZW5jZSAgCiNzYXZlUkRTKHNldSwiL1VzZXJzL3JoYWxlbmF0aG9tYXMvRG9jdW1lbnRzL0RhdGEvRmxvd0N5dG9tZXRyeS9QaGVub0lEL0FuYWx5c2lzLzlNQk8vcHJlcHJvX291dHNqYW4yMC05MDAwY2VsbHMvRmlndXJlMy9Mb3V2a242MERpZmZlcmVudENlbGxMYWJlbHMyMjAyMjAzMTguUmRzIikKICAKI3JlZmVyZW5jZSAKc2V1LnI8LSByZWFkUkRTKCIvVXNlcnMvcmhhbGVuYXRob21hcy9Eb2N1bWVudHMvRGF0YS9GbG93Q3l0b21ldHJ5L1BoZW5vSUQvQW5hbHlzaXMvOU1CTy9wcmVwcm9fb3V0c2phbjIwLTkwMDBjZWxscy9GaWd1cmUzL0xvdXZrbjYwRGlmZmVyZW50Q2VsbExhYmVsczIyMDIyMDMxOC5SZHMiKQoKCiMgZmluZCB0aGUgYW5jaG9ycyBmb3IgbGFiZWwgdHJhbnNmZXIKYW5jaG9ycyA8LSBGaW5kVHJhbnNmZXJBbmNob3JzKHJlZmVyZW5jZSA9IHNldSwgcXVlcnkgPSBzZXUucSwgZmVhdHVyZXMgPSBBQiwgcmVmZXJlbmNlLnJlZHVjdGlvbiA9ICJwY2EiLCBkaW09IDE6MTApIAojIHRoaXMgc3RlcCBpcyBjb21wdXRhdGlvbmFsbHkgaW50ZW5zaXZlIGFuZCB0YWtlIGEgbG9uZyB0aW1lCgpzZXUucSA8LSBJbnRlZ3JhdGVEYXRhKGFuY2hvcnNldCA9IGFuY2hvcnMsIG5ldy5hc3NheS5uYW1lID0gJ2ludGVncmF0ZWQnLCBkaW1zID0gMToxMCwgZmVhdHVyZXMgPSBBQikKCgpgYGAKCgoKCgoKTWF5YmUgdGhlIGRvdHBsb3QgY2FuIHdvcmsgbm93Pz8/ICBOb3BlIC0gYnV0IGl0IHdvcmtlZCBvbmNlIGJlZm9yZSBzbyB3aHkgbm90IG5vdz8/Pz8KCgpgYGB7cn0Kc2V1IDwtIFNjYWxlRGF0YShzZXUpCkRvdFBsb3Qoc2V1LCBmZWF0dXJlcyA9IEFCLCBjb2xzID0gYygicmVkIiwiYmx1ZSIpLCBncm91cC5ieSA9ICdSTkFfc25uX3Jlcy4wLjQnLCBkb3Quc2NhbGUgPSA4KSArIFJvdGF0ZWRBeGlzKCkKCmBgYAoKCgoKCg==